package com.bsh.api;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import com.bsh.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.alibaba.fastjson.JSONObject;
import com.bsh.api.Exception.ApiException;
import com.bsh.utils.Constants;
import com.bsh.utils.DesUtils;
import com.bsh.utils.MD5;

/**
 * api 工具类
 * 
 * @author jane
 *
 */
public class ApiUtils {

	private static final RedisUtil ru = RedisUtil.getRu();

	/**
	 * 获取token
	 * 
	 * @param userName
	 * @param password
	 * @return
	 */
	public static String getToken(String userName, String password) {
		DesUtils des = new DesUtils();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		String dateStr = sdf.format(new Date());
		String enc = des.encrypt(String.format("%s_%s_%s", userName, password, dateStr));
		String result = ru.setex(userName, enc, Constants.TOKEN_TIMES_INT);
		System.out.println("token放redis" + result);
		return enc;
	}

	/**
	 * 检查token 内 的用户名， 暂没有做时间过期
	 * 
	 * @param userName
	 * @param token
	 * @return
	 */
	public static boolean checkToken(String userName, String token) {
		if (userName == null || token == null) {
			return false;
		}
		DesUtils des = new DesUtils();
		try {
			if (Constants.TOKEN_CHECK) {
				if (ApiUtils.objIsNotEmpty(des.decrypt(token))) {
					String str[] = StringUtils.split(des.decrypt(token), "_");
					String redisToken = ru.get(userName);
					if (!str[0].equals(userName)) {
						return false;
					}
					// 如果redis上有给加时间
					if (ApiUtils.objIsNotEmpty(redisToken) && token.equals(redisToken)) {
						System.out.println("redis上面有token");
						ru.setex(userName, token, Constants.TOKEN_TIMES_INT);
						return true;
					}
					// 如果redis上没有校验时长 超时判断
					else if (ApiUtils.objIsEmpty(redisToken)
							&& ApiUtils.checkTimeLong(str[2], new Date(), Constants.TOKEN_TIMES)) {
						System.out.println("redis上面无token");
						ru.setex(userName, token, Constants.TOKEN_TIMES_INT);
						return true;
					} else {
						return false;
					}

				} else {
					return false;
				}

			} else {
				return true;
			}

		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 外网url
	 * 
	 * @param imageDir
	 * @param request
	 * @return
	 */
	public static String getUrl(HttpServletRequest request) {

		int serverPort;
		serverPort = request.getServerPort();
		String url = "";
		if (serverPort == 80) {
			url = request.getServerName();
		} else {
			url = request.getServerName() + ":" + serverPort;
		}
		return "http://" + url;
	}

	/**
	 * 图片地址加外网url
	 * 
	 * @param imageDir
	 * @param request
	 * @return
	 */
	public static String imageUrl(String imageDir, HttpServletRequest request) {
		if (objIsEmpty(imageDir)) {
			return "";
		}
		int serverPort;
		serverPort = request.getServerPort();
		String url = "";
		if (serverPort == 80) {
			url = request.getServerName();
		} else {
			url = request.getServerName() + ":" + serverPort;
		}
		return "http://" + url + imageDir;
	}

	/**
	 * 图片地址去掉url
	 * 
	 * @param imageUrlDir
	 * @param request
	 * @return
	 */
	public static String removeImageUrl(String imageUrlDir, HttpServletRequest request) {
		if (!imageUrlDir.matches("http(.*)")) {
			return imageUrlDir;
		}
		int serverPort;
		serverPort = request.getServerPort();
		String url = "";
		if (serverPort == 80) {
			url = request.getServerName();
		} else {
			url = request.getServerName() + ":" + serverPort;
		}
		url = "http://" + url;
		String imageDir = imageUrlDir.substring(url.length(), imageUrlDir.length());
		return imageDir;
	}

	/**
	 * 图片地址去掉url
	 * 
	 * @param imageUrlDir
	 * @param request
	 * @return
	 */
	public static String removeImageUrl(String imageUrlDir, String url) {
		if (!imageUrlDir.matches("http(.*)")) {
			return imageUrlDir;
		}
		String imageDir = imageUrlDir.substring(url.length(), imageUrlDir.length());
		return imageDir;
	}

	/**
	 * 手机号验证
	 * 
	 * @param str
	 * @return 验证通过返回true
	 */
	public static boolean isMobile(String str) {
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); // 验证手机号
		m = p.matcher(str);
		b = m.matches();
		return b;
	}

	/**
	 * 校验名字合法
	 * 
	 * @param str
	 * @return 验证通过返回true
	 */
	public static boolean isName(String str) {
		return str.matches("^[\u4e00-\u9fa5]{1,20}?$");

	}

	/**
	 * 获取图片前url
	 * 
	 * @param request
	 * @return
	 */
	public static String getPicUrl(HttpServletRequest request) {
		int serverPort;
		serverPort = request.getServerPort();
		String url = "";
		if (serverPort == 80) {
			url = request.getServerName();
		} else {
			url = request.getServerName() + ":" + serverPort;
		}
		return "http://" + url;
	}

	/**
	 * 判断对象是否Empty(null或元素为0)<br>
	 * 实用于对如下对象做判断:Integer String Collection及其子类 Map及其子类
	 * 
	 * @param pObj
	 *            待检查对象
	 * @return boolean 返回的布尔值
	 */
	@SuppressWarnings("rawtypes")
	public static boolean objIsEmpty(Object pObj) {
		if (pObj == null)
			return true;
		if (pObj == "")
			return true;
		if (pObj instanceof String) {
			if (((String) pObj).length() == 0) {
				return true;
			}
		} else if (pObj instanceof Collection) {
			if (((Collection) pObj).size() == 0) {
				return true;
			}
		} else if (pObj instanceof Map) {
			if (((Map) pObj).size() == 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断对象是否为NotEmpty(!null或元素>0)<br>
	 * 实用于对如下对象做判断:Integer String Collection及其子类 Map及其子类
	 * 
	 * @param pObj
	 *            待检查对象
	 * @return boolean 返回的布尔值
	 */
	@SuppressWarnings("rawtypes")
	public static boolean objIsNotEmpty(Object pObj) {
		if (pObj == null)
			return false;
		if (pObj == "")
			return false;
		if (pObj instanceof String) {
			if (((String) pObj).length() == 0) {
				return false;
			}
		} else if (pObj instanceof Collection) {
			if (((Collection) pObj).size() == 0) {
				return false;
			}
		} else if (pObj instanceof Map) {
			if (((Map) pObj).size() == 0) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 返回去除连接符-的UUID
	 * 
	 * @return
	 */
	public static String uuid() {
		String uuid = uuid2();
		return uuid.replaceAll("-", "");
	}

	/**
	 * 返回原生UUID
	 * 
	 * @return
	 */
	public static String uuid2() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 返回原始UUID中指定序号的一组字符串。
	 * 
	 * @param index
	 *            有效索引序号[0,1,2,3,4]。
	 * @return
	 */
	public static String uuid(int index) {
		String[] uuids = uuid().split("-");
		return uuids[index];
	}

	/**
	 * java生成随机数字和字母组合
	 * 
	 * @param length[生成随机数的长度]
	 * @return
	 */
	public static String getCharAndNumr(int length) {
		String val = "";
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			// 输出字母还是数字
			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
			// 字符串
			if ("char".equalsIgnoreCase(charOrNum)) {
				// 取得大写字母还是小写字母
				int choice = 97;
				val += (char) (choice + random.nextInt(26));
			} else if ("num".equalsIgnoreCase(charOrNum)) { // 数字
				val += String.valueOf(random.nextInt(10));
			}
		}
		return val;
	}

	/**
	 * 检查userName和token是否存在是否合法
	 * 
	 * @param json
	 * @throws ApiException
	 */
	public static void checkUserNameToken(JSONObject json) throws ApiException {
		if (ApiUtils.objIsEmpty(json.getString("userName"))) {
			throw new ApiException("105", "缺少用户名");
		}
		if (ApiUtils.objIsEmpty(json.getString("token"))) {
			throw new ApiException("103", "缺少token");
		} else if (!ApiUtils.checkToken(json.getString("userName"), json.getString("token"))) {
			throw new ApiException("104", "请重新登录");
		}
	}

	/**
	 * 查询时间间隔是否大于指定时间
	 * 
	 * @param start
	 *            开始时间
	 * @param end
	 *            结束时间
	 * @param between
	 *            时间间隔 秒
	 * @return
	 */
	public static boolean checkTimeLong(String start, Date endTime, long between) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			Date startTime = sdf.parse(start);
			return !(endTime.getTime() - startTime.getTime() < 0
					|| (endTime.getTime() - startTime.getTime()) / 1000 > between);
		} catch (ParseException e) {
			return false;
		}
	}

	/**
	 * 查询开始时间是否大于注册时间分界
	 * 
	 * @param start
	 *            开始时间
	 * @param end
	 *            结束时间
	 * @param between
	 *            时间间隔 秒
	 * @return
	 * @throws ParseException
	 */
	public static boolean checkTime(Date startTime) throws ApiException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date endTime = null;
		try {
			endTime = sdf.parse(Constants.REG_TIME_LINE);
		} catch (ParseException e) {
			throw new ApiException("400", "时间配置错误");
		}
		return startTime.compareTo(endTime) < 0;
	}

	/**
	 * 生成微信sign
	 * 
	 * @return
	 */

	public static String createWxSign(String nonce_str) {
		String str = "appid=" + Constants.WX.APP_ID + "&body=" + Constants.WX.BODY + "&device_info="
				+ Constants.WX.DEVICE_INFO + "&mch_id=" + Constants.WX.MCH_ID + "&nonce_str=" + nonce_str + "&key="
				+ Constants.WX.KEY;
		String sign = MD5.GetMD5Code(str).toUpperCase();
		return sign;

	}

	public static void main(String[] args) throws ParseException, InterruptedException, ApiException {
		JSONObject json = new JSONObject();
		String nonceStr = ApiUtils.uuid();
		json.put("appid", Constants.WX.APP_ID);
		json.put("mch_id", Constants.WX.MCH_ID);
		json.put("device_info", Constants.WX.DEVICE_INFO);
		json.put("body", Constants.WX.BODY);
		json.put("trade_type", Constants.WX.TRADE_TYPE);
		json.put("nonce_str", nonceStr);
		json.put("sign", ApiUtils.createWxSign(nonceStr));
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("xml");
		Element appid = root.addElement("appid");
		appid.addText(json.getString("appid"));
		Element body = root.addElement("body");
		body.addText(json.getString("body"));
		Element device_info = root.addElement("device_info");
		device_info.addText(json.getString("device_info"));
		Element mch_id = root.addElement("mch_id");
		mch_id.addText(json.getString("mch_id"));
		Element nonce_str = root.addElement("nonce_str");
		nonce_str.addText(json.getString("nonce_str"));
		Element sign = root.addElement("sign");
		sign.addText(json.getString("sign"));
		Element trade_type = root.addElement("trade_type");
		trade_type.addText(json.getString("trade_type"));
		String output = document.asXML();
		System.out.println(output);

	}
}
